/**
 * 安卓包专用缓存工具（基于原生文件系统）
 * 支持：大容量二进制文件存储、过期时间控制、按前缀清理、容量限制。
 * 注意：此版本仅适用于安卓包（APP-PLUS），H5端不兼容。
 */

// 存储所有缓存元数据的Key（文件名、路径、大小、过期时间等）
const CACHE_META_KEY = 'cache_meta_data';

/**
 * 1. 核心缓存操作：设置缓存（保存文件到本地）
 * @param {string} key - 缓存唯一标识（建议加模块前缀，如 "tts_cache_xxx"）
 * @param {ArrayBuffer} value - 要缓存的二进制数据（如音频流）
 * @param {number} expire - 过期时间（毫秒，如 5*24*60*60*1000 表示5天）
 * @returns {Promise<boolean>} 存储成功返回 true，失败返回 false
 */
export const setCache = async (key, value, expire) => {
    if (!key || !value || !(value instanceof ArrayBuffer) || expire <= 0) {
        console.error('【缓存工具】setCache：参数错误，key、有效的ArrayBuffer和正的expire是必需的');
        return false;
    }

    try {
        // a. 将 ArrayBuffer 转换为 Blob，再创建临时 URL
        const audioBlob = new Blob([value], { type: 'application/octet-stream' });
        const tempFilePath = URL.createObjectURL(audioBlob);

        // b. 使用 uni.saveFile 将临时文件保存到本地
        const saveRes = await uni.saveFile({ tempFilePath });
        if (saveRes.errMsg !== 'saveFile:ok') {
            throw new Error(`文件保存失败: ${saveRes.errMsg}`);
        }
        const savedFilePath = saveRes.savedFilePath;

        // c. 获取文件信息（特别是大小）
        const fileInfo = await uni.getSavedFileInfo({ filePath: savedFilePath });

        // d. 更新缓存元数据到 uni.setStorage
        const meta = await getCacheMeta();
        meta[key] = {
            filePath: savedFilePath,
            size: fileInfo.size, // 记录文件大小，用于容量控制
            expireAt: Date.now() + expire
        };
        await uni.setStorage({ key: CACHE_META_KEY, data: JSON.stringify(meta) });

        console.log(`【缓存工具】setCache：成功存储文件 key=${key}，路径=${savedFilePath}，大小=${(fileInfo.size/1024).toFixed(2)}KB`);
        return true;
    } catch (error) {
        console.error(`【缓存工具】setCache：存储失败 key=${key}`, error);
        return false;
    }
};

/**
 * 2. 核心缓存操作：获取缓存（返回文件路径）
 * @param {string} key - 缓存唯一标识
 * @returns {Promise<string|null>} 未过期返回文件本地路径，否则返回 null
 */
export const getCache = async (key) => {
    if (!key) {
        console.error('【缓存工具】getCache：key 不能为空');
        return null;
    }

    try {
        const meta = await getCacheMeta();
        const item = meta[key];

        if (!item) {
            console.log(`【缓存工具】getCache：key=${key} 未命中`);
            return null;
        }

        // 检查是否过期
        if (Date.now() > item.expireAt) {
            await removeCache(key); // 自动删除过期缓存
            console.log(`【缓存工具】getCache：key=${key} 已过期，已自动清理`);
            return null;
        }

        // 验证文件是否还存在（可能被系统或用户清理）
        try {
            await uni.getSavedFileInfo({ filePath: item.filePath });
            console.log(`【缓存工具】getCache：key=${key} 命中，路径=${item.filePath}`);
            return item.filePath; // 返回文件路径，供播放器使用
        } catch (fileError) {
            console.warn(`【缓存工具】getCache：文件不存在，清理无效元数据 key=${key}`, fileError);
            await removeCache(key);
            return null;
        }
    } catch (error) {
        console.error(`【缓存工具】getCache：读取失败 key=${key}`, error);
        return null;
    }
};

/**
 * 3. 缓存清理：删除指定 key 的缓存
 * @param {string} key - 缓存唯一标识
 * @returns {Promise<void>}
 */
export const removeCache = async (key) => {
    if (!key) return;

    try {
        const meta = await getCacheMeta();
        const item = meta[key];

        if (item) {
            // 先删除文件
            try {
                await uni.removeSavedFile({ filePath: item.filePath });
                console.log(`【缓存工具】removeCache：已删除文件 key=${key}，路径=${item.filePath}`);
            } catch (fileError) {
                console.warn(`【缓存工具】removeCache：删除文件失败，可能已不存在 key=${key}`, fileError);
            }
            // 再删除元数据
            delete meta[key];
            await uni.setStorage({ key: CACHE_META_KEY, data: JSON.stringify(meta) });
            console.log(`【缓存工具】removeCache：已删除元数据 key=${key}`);
        }
    } catch (error) {
        console.error(`【缓存工具】removeCache：清理失败 key=${key}`, error);
    }
};

/**
 * 4. 缓存清理：批量清理「指定前缀」的所有过期缓存，并进行容量控制
 * @param {string} prefix - 缓存 key 前缀（如 "tts_cache_"）
 * @param {number} [maxSize=100*1024*1024] - 缓存最大容量（字节），默认100M
 * @returns {Promise<void>}
 */
export const clearExpiredCacheByPrefix = async (prefix, maxSize = 100 * 1024 * 1024) => {
    if (!prefix) {
        console.error('【缓存工具】clearExpiredCacheByPrefix：prefix 不能为空');
        return;
    }

    try {
        const meta = await getCacheMeta();
        const keys = Object.keys(meta);
        if (keys.length === 0) return;

        const now = Date.now();
        const expiredKeys = [];
        const validItems = [];

        // 1. 筛选出过期的和有效的缓存项
        for (const key of keys) {
            if (key.startsWith(prefix)) {
                const item = meta[key];
                if (now > item.expireAt) {
                    expiredKeys.push(key);
                } else {
                    validItems.push({ key, ...item });
                }
            }
        }

        // 2. 删除所有过期的缓存
        for (const key of expiredKeys) {
            await removeCache(key);
        }

        // 3. 计算剩余有效缓存的总大小
        const totalValidSize = validItems.reduce((sum, item) => sum + item.size, 0);

        // 4. 如果总大小超过限制，按过期时间（最早的先删）删除，直到低于限制
        if (totalValidSize > maxSize) {
            console.log(`【缓存工具】clearExpiredCacheByPrefix：缓存总大小 ${(totalValidSize/1024/1024).toFixed(2)}M 超过 ${(maxSize/1024/1024)}M 限制，开始清理...`);

            // 按过期时间升序排序（最早过期的在前面）
            validItems.sort((a, b) => a.expireAt - b.expireAt);

            let currentSize = totalValidSize;
            for (const item of validItems) {
                await removeCache(item.key);
                currentSize -= item.size;
                console.log(`【缓存工具】clearExpiredCacheByPrefix：为控容删除 key=${item.key}，当前大小=${(currentSize/1024/1024).toFixed(2)}M`);

                if (currentSize <= maxSize) {
                    break; // 达到容量要求，停止删除
                }
            }
        }

        console.log(`【缓存工具】clearExpiredCacheByPrefix：前缀=${prefix}，清理完成`);
    } catch (error) {
        console.error('【缓存工具】clearExpiredCacheByPrefix：批量清理失败', error);
    }
};

/**
 * 5. 缓存清理：清空所有缓存（谨慎使用！）
 * @returns {Promise<void>}
 */
export const clearAllCache = async () => {
    try {
        // 弹出确认框（仅在H5调试时有效，App端可能无此API，需自行实现）
        // if (confirm('确认要清空所有缓存文件吗？')) {
        const meta = await getCacheMeta();
        const keys = Object.keys(meta);

        for (const key of keys) {
            await removeCache(key);
        }
        console.log('【缓存工具】clearAllCache：已清空所有缓存文件和元数据');
        // }
    } catch (error) {
        console.error('【缓存工具】clearAllCache：清空失败', error);
    }
};

/**
 * 内部辅助函数：获取所有缓存的元数据
 * @returns {Promise<object>} 元数据对象
 */
const getCacheMeta = async () => {
    try {
        const res = await uni.getStorage({ key: CACHE_META_KEY });
        return res.data ? JSON.parse(res.data) : {};
    } catch (error) {
        // 如果是 "key not found" 错误，返回空对象
        if (error.errMsg && error.errMsg.includes('key not found')) {
            return {};
        }
        console.error('【缓存工具】getCacheMeta：获取元数据失败', error);
        return {};
    }
};

// --- H5 端兼容提示（可删除或注释）---
// 这段代码用于在 H5 环境下给出明确的错误提示，防止误用。
// #ifdef H5
console.warn('⚠️ 警告：当前使用的 cache.js 是安卓包专用版本，H5 环境下不兼容。请切换到 H5 专用的 localStorage 版本。');
// #endif